<?php
	
	class Physician_Model extends CI_Model{
		
		function Physician_Model(){
                parent::__construct();
                $this->load->library("Physician");
                $this->load->library("Patient");
                $this->load->library("Message");
                $this->load->library("Note");  
                
                $this->load->helper("Utils");
                $this->load->helper("Constants");
        }
        
        
        /**
         * get attributes from the param, Physician object, and
         * save each attribute on the Physician table..
         * @param $physician
         */
		function savePhysician(Physician $physician){

			$data = array(
						   
						   'firstName' => $physician->getFirstName(),
						   'lastName' => $physician->getLastName(),
						   'email' => $physician->getEmail(),
						   'gender' => $physician->getGender(),
						   'birthDate' => $physician->getBirthDate(),
						   'title' => $physician->getTitle(),
						   'password' => $physician->getPassword(),
						   'note' => $physician->getNote(),
						   'employed' => $physician->getEmployed(),
						   'status' => $physician->getStatus(),
						   'phoneNumber' => $physician->getPhoneNumber(),
					       'birthPlaceCity' => $physician->getBirthPlaceCity(),
					       'birthPlaceCountry' => $physician->getBirthPlaceCountry(),
					       'address' => $physician->getAddress(),
					);
			
			$this->db->insert('Physician', $data);  
			
			return $this->db->insert_id() ; 
		}
	
		
		/**
		 * get Physician by Id from physician table, 
		 * @param $id, physicianId
		 * @returns physician object
		 */
		function getPhysicianById($id){		
			$q = $this->db->get_where('Physician', array('id'=>$id) ) ;
			$result = $q->result_array();
			
			$physician = new Physician();
			$physician =  Utils::createPhysicianObject($result); // pass $result[0] ?
			
			return $physician;
		}
		
		
		/**
		 * get Physician by email from physician table, 
		 * @param $email, physician's email
		 * @returns physician object
		 */
		function getPhysicianByEmail($email){
			$q = $this->db->get_where('Physician', array('email'=>$email) ) ;
			$result = $q->result_array();
			
			$physician = new Physician();
			$physician = Utils::createPhysicianObject($result);  
			
			return $physician;
		}

		
		/**
		 * get Physician by first name and full name from physician table, 
		 * @param $firstName, $lastName, 
		 * @returns physician object
		 */
		function getPhysicianByName($firstName, $lastName){
			$q = $this->db->get_where('Physician', array('firstName'=>$firstName, 'lastName'=>$lastName) ) ;
			$result = $q->result_array();
			
			$physician = new Physician();
			$physician = Utils::createPhysicianObject($result);  
			
			return $physician;
		}
		
		
		/**
		 * get Physicians (NB plural) by first name, eg for searching  
		 * @param $firstName, 
		 * @returns physicians array
		 */
		function getPhysiciansByName($firstName){
			$q = $this->db->get_where('Physician', array('firstName'=>$firstName) ) ;
			$result = $q->result_array();
			
			$physicians = array();
			foreach ($result as $row){
				$physician = new Physician();
				$physician = Utils::createPhysicianObject($result);  
				$physicians[] = $physician;
			}
			
			return $physicians;
		}
		
		
		/**
		 * get Physicians (NB plural) by email, search
		 * @param $email, = could be part of the email, e.g. for suggestion box
		 * @returns physicians array
		 */
		function getPhysiciansByEmail($email){
			$q = $this->db->get_where('Physician', array('email'=>$email) ) ;
			$result = $q->result_array();
			
			$physicians = array();
			foreach ($result as $row){
				$physician = new Physician();
				$physician = Utils::createPhysicianObject($result);  
				$physicians[] = $physician;
			}
			
			return $physicians;
		}
		
		
		/**
		 * get Physician by email and password from physician table, 
		 * @param $email, $password
		 * @returns physician object
		 */
		function getPhysicianByEmailAndPassword($email, $password){
			$q = $this->db->get_where('Physician', array('email'=>$email, "password" => $password) ) ;
			$result = $q->result_array();
			
			$physician = new Physician();
			$physician = Utils::createPhysicianObject($result); // pass $result[0] ?
			
			return $physician;
		}

		
		/**
		 * Deletes physician with $id from the physician table
		 * Deletes all dependancies first from other tables.
		 * @param $id
		 */
		function deletePhysician($id){
			$this->db->delete('Laboratory', array('orderingPhysicianId' => $id));
			$this->db->delete('Laboratory', array('labTechnicianPhysicianId' => $id));
			
			$this->db->delete('Medication', array('physicianId' => $id));
			
			$this->db->delete('Visit', array('physicianId' => $id));
			
			$this->db->delete('Day', array('physicianId' => $id));
			
			$this->db->delete('Radiology', array('physicianId' => $id));
			
			$this->db->delete('Note', array('physicianId' => $id));
			
			$this->db->delete('Vitals', array('physicianId' => $id));
			$this->db->delete('Vitals', array('testingPhysicianId' => $id));
			
			$this->db->delete('Ward', array('physicianId' => $id));
			
			
			$this->db->delete('Message', array('senderPhysicianId' => $id));
			$this->db->delete('Message', array('recipientPhysicianId' => $id));
			
			$this->db->delete('Physician', array('id' => $id));
		}
		
		
		/**
		 * get all patients of the physician with $id
		 * @param $id
		 * @returns patients array
		 */
		function getAllPatients($id){
			$this->db->select('*');
			$this->db->from('Patient');
			$this->db->join('Visit', 'Visit.patientId = Patient.id');
			$this->db->where('Visit.physicianId', $id); 
			
			$query = $this->db->get();
		}
		
		
		/**
		 * get all patients of the physician with $id, patients who are currently
		 * being treated by the physician, not discharged, status = IN
		 * @param $id
		 * @returns patients array
		 */
		function getInPatients($id){
			$this->db->select('*');
			$this->db->from('Patient');
			$this->db->join('Visit', 'Visit.patientId = Patient.id');
			$this->db->where('Visit.physicianId', $id); 
			$this->db->where('Patient.status', Constants::PATIENT_STATUS_IN); 
			
			$query = $this->db->get();
		}
		
		
		/**
		 * get all patients of the physician with $id, patients who are NOT currently
		 * being treated by the physician, discharged, status = out
		 * @param $id
		 * @returns patients array
		 */
		function getOutPatients($id){
			$this->db->select('*');
			$this->db->from('Patient');
			$this->db->join('Visit', 'Visit.patientId = Patient.id');
			$this->db->where('Visit.physicianId', $id); 
			$this->db->where('Patient.status', Constants::PATIENT_STATUS_OUT); 
			
			$query = $this->db->get();
		}
		
		
		/**
		 * get all patients assigned to the physician with $id, but not 
		 * accepted by the physician yet, status = NEW
		 * @param $id
		 * @returns patients array
		 */
		function getNewPatients($id){
			$this->db->select('*');
			$this->db->from('Patient');
			$this->db->join('Visit', 'Visit.patientId = Patient.id');
			$this->db->where('Visit.physicianId', $id); 
			$this->db->where('Patient.status', Constants::PATIENT_STATUS_NEW); 
			
			$query = $this->db->get();
		}
		
		
		/**
		 * Accept a patient to the 'hospital' e.g. at the reception
		 * 
		 * Create a new entry in the Visit and Day tables.
		 * Physician not assigned yet, Patient.status = UNASSIGNED.
		 * @param $patientId
		 */
		function checkInPatient($patientId, $caseDescription, $note){
			// create a new entry in Visit table
			$visitInput = array(
				'patientId' => $patientId,
				'caseDescription' => $caseDescription,
				'note' => $note,
				'accepted' => new DateTime('now')
			);
			$visitId = $this->db->insert('Visit', $visitInput);

			// create a new entry in Day table
			$dayInput = array(
				'visitId' => $visitId,
				'patientId' => $patientId,
				'number' => 1,
				'caseDescription' => $caseDescription,
				'note' => $note
			);
			$dayId = $this->db->insert('Day', $dayInput);
			
			// update the patient status to unassigned
			$this->db->where('id', $id);
			$this->db->update('Patient', array('status'=>Constants::PATIENT_STATUS_UNASSIGNED)); 
		}
		
		
		/**
		 * To assign a physician to a patient, get the latest visit of the patient
		 * and assign the physician to that visit. and to the days of the visit.
		 * And update the status of the patient to NEW
		 * 
		 * @param $patientId, $physicianId
		 */
		function assignPhysician($patientId, $physicianId){
			$visitId = $this->getLatestVisitId($patientId);
			
			// assign the physician to the visit of the patient
			$this->db->where('id', $visitId);
			$this->db->update('Visit', array('physicianId', $physicianId));
			
			// assign the physician to all the days of visit of the patient
			$this->db->where('visitId', $visitId);
			$this->db->update('Day', array('physicianId', $physicianId));
			
			// update the status of the patient -> NEW
			$this->db->where('id', $patientId);
			$this->db->update('Patient', array('status', Constants::PATIENT_STATUS_NEW));
		}
		
		/**
		 * set the status of the patient to IN, physician accepts the patient
		 * 
		 * There might be a case where the physician takes a patient from a list 
		 * which means he assigns the patient to himself and accept at the same time.
		 * In that case, we do the assignment here again,
		 * 
		 * @param $physicianId
		 * @param $patientId
		 */
		function acceptPatient($physicianId, $patientId){
			$visitId = $this->getLatestVisitId($patientId);
			
			// assign the physician to the visit of the patient, this may have been done already, just in case
			$this->db->where('id', $visitId);
			$this->db->update('Visit', array('physicianId', $physicianId));
			
			// assign the physician to all the days of visit of the patient, this may have been done already
			$this->db->where('visitId', $visitId);
			$this->db->update('Day', array('physicianId', $physicianId));
			
			// update the status of the patient -> NEW
			$this->db->where('id', $patientId);
			$this->db->update('Patient', array('status', Constants::PATIENT_STATUS_IN));
			
		}
		
		
		function rejectPatient($physicianId, $patientId){
			$visitId = $this->getLatestVisitId($patientId);
			
			// assign a NULL physician to the visit of the patient,
			$this->db->where('id', $visitId);
			$this->db->update('Visit', array('physicianId', NULL));
			
			// assign NULL physician to all the days of visit of the patient,
			$this->db->where('visitId', $visitId);
			$this->db->update('Day', array('physicianId', NULL));
			
			// update the status of the patient -> rejected
			$this->db->where('id', $patientId);
			$this->db->update('Patient', array('status', Constants::PATIENT_STATUS_REJECTED));
		}
		
		/**
		 * update the status of the patient - out
		 * update Visit: lengthOfStay, discharged
		 * 
		 * @param $patientId
		 */
		function dischargePatient($patientId){
			$visitId = $this->getLatestVisitId($patientId);
			
			$latestVisits = $this->getLatestVisits($patientId);
			$latestVisit = $latestVisits[0];
			$accepted = $latestVisit->getAccepted();
			
			$data = array(
               'discharged' => new DateTime('now'),
               'lengthOfStay' => Utils::calculateLengthOfStay($accepted, new DateTime('now'))
            );
			
			$this->db->where('id', $visitId);
			$this->db->update('Visit', $data);
			 
			// update the status of the patient -> rejected
			$this->db->where('id', $patientId);
			$this->db->update('Patient', array('status', Constants::PATIENT_STATUS_OUT));
		}
		
		
		/**
		 * returns visit array in descending order of accepted days
		 * @param $patientId
		 */
		function getLatestVisits($patientId){
			$this->db->order_by("Visit.accepted", "desc");
			$q = $this->db->get('Visit') ;
			$result = $q->result_array();

			$visits = array();
			foreach ($result as $row){
				$visit = new Visit();
				$visit =  Utils::createVisitObject($result); // pass $result[0] ? //TODO
				$visits[] = $visit;
			}
			
			return $visits;
		}
		
	
		/**
		 * returns the id of the latest visit 
		 * @param $patientId
		 */
		function getLatestVisitId($patientId){
			$visits = $this->getLatestVisits($patientId);
			$latestVisit = new Visit();
			$latestVisit = $visits[0];
			$visitId = $latestVisit->getId();
			
			return $visitId;
		}
		
		function updateProfile(Physician $physician){
			$data = array(
				   'firstName' => $physician->getFirstName(),
				   'lastName' => $physician->getLastName(),
				   'email' => $physician->getEmail(),
				   'gender' => $physician->getGender(),
				   'birthDate' => $physician->getBirthDate(),
				   'title' => $physician->getTitle(),
				   'password' => $physician->getPassword(),
				   'note' => $physician->getNote(),
				   'employed' => $physician->getEmployed(),
				   'status' => $physician->getStatus(),
				   'phoneNumber' => $physician->getPhoneNumber(),
			       'birthPlaceCity' => $physician->getBirthPlaceCity(),
			       'birthPlaceCountry' => $physician->getBirthPlaceCountry(),
			       'address' => $physician->getAddress(),
			);
			
			$this->db->where('id', $physician->getId());
			$this->db->update('Physician', $data);
		}
		
		function sendPatientToDepartment(){
			
		}
		
		function getChart(){
			
		}
		
		function publishCaseForDescription(){
			
		}
		
	}
	
?>